package com.googlecode.allinclusive.fw.security;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.access.SecurityMetadataSource;
import org.springframework.security.web.access.intercept.DefaultFilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.AntPathRequestMatcher;
import org.springframework.security.web.util.RequestMatcher;
import org.springframework.util.Assert;

import com.googlecode.allinclusive.fw.database.ibatis.EntityManager;

/**
 * 安全认证信息数据工厂
 * 
 * @author <a href="mailto:xiayg@cares.sh.cn">xiayg</a>
 * @version 1.0 2010-12-29
 */
public class SecurityConfigFactory implements FactoryBean<SecurityMetadataSource> {

	/**
	 * DB存取管理实例
	 */
	@Autowired
	protected EntityManager entityManager;
	
	/**
	 * 创建安全认证信息源
	 */
	@Override
	public SecurityMetadataSource getObject() throws Exception {
		// 获取HTTP资源的角色配置信息
		List<ResourceRole> resRoles = entityManager.executeForObjectList("ResourceRole.getHttpResourceRoles", null);
		
		// HTTP资源匹配器-角色映射Map
		LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap = new LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>>();
		for (ResourceRole resRole : resRoles) {
			// HTTP资源
			RequestMatcher matcher = new AntPathRequestMatcher(resRole.getUrlPattern(), resRole.getHttpMethod());
			// 该HTTP资源的角色配置信息
			Collection<ConfigAttribute> configAttributes = find(matcher, requestMap);
			if (configAttributes == null) {
				configAttributes = new ArrayList<ConfigAttribute>();
				requestMap.put(matcher, configAttributes);
			}
			configAttributes.add(new SecurityConfig(resRole.getRoleCode()));
		}
		
		return new DefaultFilterInvocationSecurityMetadataSource(requestMap);
	}

	/**
	 * 查找相同的RequestMatcher的角色配置信息
	 * @param matcher HTTP资源匹配器
	 * @param requestMap
	 * @return
	 */
	protected Collection<ConfigAttribute> find(RequestMatcher matcher, LinkedHashMap<RequestMatcher, Collection<ConfigAttribute>> requestMap) {
		// FIXME 重写AntPathRequestMatcher的hashCode？
		Assert.notNull(matcher);
		if (requestMap == null) {
			return null;
		}
		
		// 查找相同的RequestMatcher
		for (Iterator<RequestMatcher> it = requestMap.keySet().iterator(); it.hasNext(); ) {
			RequestMatcher tmpMatcher = it.next();
			if (matcher.equals(tmpMatcher)) {
				return requestMap.get(tmpMatcher);
			}
		}
		
		return null;
	}
	
	/**
	 * 创建对象的类型
	 */
	@Override
	public Class<?> getObjectType() {
		return SecurityMetadataSource.class;
	}

	/**
	 * 是否单例
	 */
	@Override
	public boolean isSingleton() {
		return true;
	}
}
